<?php

namespace App\Service\VendorClient\ShopjdApi;

use App\Service\Code\Normal;
use App\Service\BaseService;
use App\Model\PssModel\ServiceConfig;
use Service\AppService\IdService;
use App\Service\TaskServer\TaskWorker;
use App\Service\HttpServer\HttpCurl;

/**
 * 京东开普勒云交易系统供应商对接
 * 电商平台负责申报支付单，供应商申报订单和清单
 * @author hj
 */
class ShopjdkeplerClient extends BaseService {
    /**
     * redis缓存的key access_token
     */
    const TOKEN_PREFIX = '_shopjdkepler_access_token_';
    /**
     * redis缓存的key refresh_token
     */
    const REFRESH_TOKEN_PREFIX = '_shopjdkepler_refresh_token_';
    //供应商编号
    const SUPPLIER_CODE = 'shopjdkepler';

    private $redis;

    //配置文件
    private $config = [];

    public function __construct($apiBody = []) {
        $this->config = $apiBody;
        $this->redis  = $this->getRedisObj();
    }

    /**
     * 创建订单
     * @param array $params
     * @return array
     */
    public function createOrder($param = []) {
        if (empty($param['supplierOrder']) || empty($param['orderGoods']) || empty($param['order']) || empty($param['binfo'])) {
            return Normal::returnCode(Normal::FAIL, "except param supplierOrder or orderGoods or order or binfo");
        }
        $orderInfo = $param['supplierOrder'];
        $goodsList = $param['orderGoods'];
        $order     = $param['order'];
        $binfo     = $param['binfo'];
        $order_sn  = $orderInfo['supplier_dsn'];
        //订单时间
        $order_time = $orderInfo['cd'] ? date('Y-m-d H:i:s', $orderInfo['cd']) : date('Y-m-d H:i:s', time());
        //支付时间
        $pay_time = isset($order['payTime']) && !empty($order['payTime']) ? date('Y-m-d H:i:s', $order['payTime']) : date('Y-m-d H:i:s', time());
        //运费分摊
        $deliver_money = $orderInfo['deliver_money'];
        //优惠
        $discount_money = $orderInfo['discount_money'];
        //下单支付的时候支付信息
        $apply_extends = @json_decode($orderInfo['apply_extends'], true);
        //获取下单商品信息
        $orderGoodsList   = [];
        $skuList          = [];
        $goodsTotalMoney  = '0.00';
        foreach ($goodsList as $key => $item) {
            // $price            = (string)$item['price'];
            $price            = (string)$item['costprice'];//京东要传成本价
            $spec_num         = (string)$item['spec_num'];
            $quantity         = (string)$item['quantity'];
            $supplier_skucode = $item['supplier_skucode'];
            $goods_type       = $item['goods_type'];
            $goodsMoney = bcmul($price, $quantity, 2);
            //下单商品组
            $goodsInfo               = [
                'mainSku' => [
                    'skuId'         => trim($item['supplier_skucode']),//京东商品编号
                    'skuPrice'      => $price,//商品单价，单位：元
                    'quantity'      => $quantity,//商品数量
                    'skuName'       => $item['goods_name'],//商品名称
                ]
            ];
            $skuList[]               = [
                'skuPrice' => $price,
                'skuId'    => trim($item['supplier_skucode']),
                'skuName'  => $item['goods_name'],
                'quantity' => $quantity,
            ];
            $orderGoodsList[]        = $goodsInfo;
            $goodsTotalMoney         = bcadd((string)$goodsTotalMoney, $goodsMoney, 2);
        }
        //用户实际支付金额
        $real_total_money = $orderInfo['real_total_money'];
        $address = [
            'provinceId'  => 0,//京东标准省ID，若使用国标地址固定传0
            'cityId'      => 0,//京东标准市ID，若使用国标地址固定传0
            'countyId'    => 0,//京东标准县ID，若使用国标地址固定传0
            'townId'      => 0,//京东标准镇ID，若使用国标地址固定传0（北京 省 市id是一样的【例如：北京 -北京 -通州区-台湖镇】，那么townid =台湖镇）
            'fullAddress' => $orderInfo['province'] . $orderInfo['city'] . $orderInfo['district'] . $orderInfo['receive_address'],//详细全地址信息，必须传入
        ];
        //获取运费
        $getFreightFee = $this->getFreightFee(['orderFee' => $goodsTotalMoney, 'skuList' => $skuList, 'address' => $address]);
        if ($getFreightFee['code'] != Normal::SUC) {
            return Normal::returnCode(Normal::FAIL, "获取运费失败【{$getFreightFee['msg']}】", $getFreightFee['data']);
        }
        //获取配送方式
        $getShipmentType = $this->getShipmentType(['skuList' => $skuList, 'address' => $address]);
        if ($getShipmentType['code'] != Normal::SUC) {
            return Normal::returnCode(Normal::FAIL, "获取配送方式失败【{$getShipmentType['msg']}】", $getShipmentType['data']);
        }
        //如果此接口返回的是 9：不支持配送，则客户商城内可直接提示用户：抱歉，该商品在当前地址下不支持销售
        if ($getShipmentType['data'] == 9) {
            return Normal::returnCode(Normal::FAIL, "抱歉，该商品在当前地址下不支持配送");
        }
        $orderList = [
            'protocol' => [
                'customerId' => $this->config['customerId'],//客户id，客户唯一身份标识
                'appKey'     => $this->config['appKey'],//客户应用唯一标识
                'channelId'  => $this->config['channelId'],//渠道id，客户对应的细分渠道标识
            ],
            'param'    => [
                'channelOrderId'     => $order_sn,//渠道订单号，交易唯一标识，来源：三方渠道
                'pin'                => $this->config['pin'],//下单账号
                'productList'        => $orderGoodsList,//商品信息列表，最多：30个商品
                'orderFee'           => $goodsTotalMoney,//商品总金额，单位：元（不包含运费）
                'freightFee'         => $getFreightFee['data'],//'需要去查询  获取运费 API',//运费金额 单位：元
                'address'            => $address,
                'receiver'           => [
                    'receiverName'   => $orderInfo['receive_name'],//收货人姓名
                    'receiverMobile' => $orderInfo['recveive_phone'],//收货人手机号
                    'receiverEmail'  => 'wendy@bdys0ft.com',//收货人邮箱 如获取不到，可传固定值
                    'zipCode'        => '230000',//收货地邮政编码 如获取不到，可传固定值
                ],
                'paymentType'        => 2,//支付方式。固定传2：在线支付
                'shipmentType'       => $getShipmentType['data'],//'需要去查询 获取配送方式API',//配送方式。1：京东配送 2：京配转三方配送 3：第三方配送 4：普通快递配送 9不支持配送
                'channelOrderSource' => 'OTHER',//OTHER：其他
                'sendGoods'          => 1,//物品类型。固定传1
                'invoice'            => [
                    'invoiceType' => 2,//发票类型。2：纸质专票，3：电子普票
                    'vatInvoice'  => [
                        'companyName'     => '安徽空港百大启明星跨境电商有限公司',//增票资质公司名称
                        'code'            => '91340100MA2MWLJE8R',//增票资质公司纳税人标识号，来源：三方
                        'regAddr'         => '安徽省合肥市经济技术开发区云谷路以南、桃枝路以东合肥出口加工区综合业务楼1001#室',//增票资质公司注册地址
                        'regPhone'        => '0551-65771000',//增票资质公司注册电话
                        'regBank'         => '中国建设银行股份有限公司合肥华侨城支行',//增票资质公司注册银行
                        'regBankAccount'  => '34050110225100000088',//增票资质公司注册银行帐号
                        'consigneeName'   => '姚亚文',//增票邮寄收件人姓名
                        'consigneeMobile' => '15357924052',//增票邮寄收件人电话
                        'vatAddress'      => [
                            'vatProvinceId'  => 0,//京东标准省ID，来源：若使用国标地址固定传0
                            'vatCityId'      => 0,//京东标准省ID，来源：若使用国标地址固定传0
                            'vatCountyId'    => 0,//京东标准省ID，来源：若使用国标地址固定传0
                            'vatTownId'      => 0,//京东标准省ID，来源：若使用国标地址固定传0
                            'vatFullAddress' => '安徽省合肥市蜀山区黄山路596号合肥百大7楼',//详细全地址信息，必须传入
                        ],
                    ]
                ],
                'userIp'             => $this->config['ycIp'],//用户IP地址
                // 'discountFee'        => $channel_discount_amount,//订单优惠金额，其值与sku维度的优惠金额总和相等
            ]
        ];
        $data      = [
            'method' => 'createOrder',// jingdong.ctp.order.submitOrder
            'data'   => $orderList,
        ];
        $pushRes   = $this->execute($data);
        if ($pushRes['code'] != Normal::SUC) {
            return $pushRes;
        }
        if (!isset($pushRes['data']['result']['data']['orderId'])) {
            return Normal::returnCode(Normal::FAIL, "获取京东订单号失败", $pushRes['data']);
        }
        $jdOrderSn = $pushRes['data']['result']['data']['orderId'];
        return Normal::returnCode(Normal::SUC, "推送订单成功", [
            'thirdpart_order_sn' => $jdOrderSn,
        ]);
    }

    /**
     * 获取运费
     * ['orderFee' => $goodsTotalMoney, 'skuList' => $skuList, 'address' => $address]
     * @return array
     * @author: hj
     */
    public function getFreightFee($param) {
        $data   = [
            'method' => 'getFreightFee',// jingdong.ctp.order.getFreightFee
            'data'   => [
                'protocol'           => [
                    'customerId' => $this->config['customerId'],//客户id，客户唯一身份标识
                    'appKey'     => $this->config['appKey'],//客户应用唯一标识
                    'channelId'  => $this->config['channelId'],//渠道id，客户对应的细分渠道标识
                ],
                'apiFreightFeeParam' => [
                    'paymentType' => 2,//支付方式。固定传2：在线支付
                    'skuList'     => $param['skuList'],
                    'pin'         => $this->config['pin'],//下单账号
                    'orderFee'    => $param['orderFee'],
                    'address'     => $param['address']
                ],
            ],
        ];
        $result = $this->execute($data);
        if ($result['code'] != Normal::SUC) {
            return $result;
        }
        if (!isset($result['data']['result']['data']['freightFee'])) {
            return Normal::returnCode(Normal::FAIL, "获取运费失败", $result['data']);
        }
        $freightFee = $result['data']['result']['data']['freightFee'];
        return Normal::returnCode(Normal::SUC, "请求成功", $freightFee);
    }

    /**
     * 获取配送方式
     * ['skuList' => $skuList, 'address' => $address]
     * @return array
     * @author: hj
     */
    public function getShipmentType($param) {
        $data   = [
            'method' => 'getShipmentType',// jingdong.ctp.order.getShipmentType
            'data'   => [
                'protocol'             => [
                    'customerId' => $this->config['customerId'],//客户id，客户唯一身份标识
                    'appKey'     => $this->config['appKey'],//客户应用唯一标识
                    'channelId'  => $this->config['channelId'],//渠道id，客户对应的细分渠道标识
                    'traceId'    => uuid4(),//客户每次请求的唯一标识，用于单纯标识一次请求，每次请求唯一
                ],
                'apiShipmentTypeParam' => [
                    'paymentType' => 2,//支付方式。固定传2：在线支付
                    'skuList'     => $param['skuList'],
                    'pin'         => $this->config['pin'],//下单账号
                    'address'     => $param['address']
                ],
            ],
        ];
        $result = $this->execute($data);
        if ($result['code'] != Normal::SUC) {
            return $result;
        }
        if (!isset($result['data']['result']['data']['shipmentType'])) {
            return Normal::returnCode(Normal::FAIL, "获取运费失败", $result['data']);
        }
        $freightFee = $result['data']['result']['data']['shipmentType'];
        return Normal::returnCode(Normal::SUC, "请求成功", $freightFee);
    }

    /**
     * 申请取消订单接口
     * @param $data
     * @return array
     */
    public function cancelOrder($params = []) {
        $data   = [
            'method' => 'cancelOrder',// jingdong.ctp.order.cancelOrder
            'data'   => [
                'customerId'       => $this->config['customerId'],//客户id，客户唯一身份标识
                'appKey'           => $this->config['appKey'],//客户应用唯一标识
                'channelId'        => $this->config['channelId'],//渠道id，客户对应的细分渠道标识
                'orderId'          => $params['supplierOrder']['thirdpart_order_sn'],//京东订单号
                'pin'              => $this->config['pin'],//下单账号
                //取消原因 来源 1：订单不能按预计时间送达 2：其他渠道价格更低 3：该商品降价了 4：不想买了 5：其他原因 6：操作有误（商品、地址等选错） 7：商品无货 100：其他
                'cancelReasonCode' => 5,
            ],
        ];
        $result = $this->execute($data);
        if ($result['code'] != Normal::SUC) {
            return $result;
        }
        //异步接入取消申请，则状态 1：取消申请失败 3：取消申请成功（通过订单取消MQ获取取消是否成功的结果）
        if (!isset($result['data']['result']['data']['cancelStatus'])) {
            return Normal::returnCode(Normal::FAIL, "申请取消订单失败", $result['data']);
        }
        $cancelStatus = $result['data']['result']['data']['cancelStatus'];
        if ($cancelStatus == 3) {
            return Normal::returnCode(Normal::SUC, "申请取消订单成功", $result['data']);
        }
        return Normal::returnCode(Normal::FAIL, "申请取消订单失败", $result['data']);
    }

    /**
     * 查询物流
     * @param $orderSupplier
     * @return array
     */
    public function queryOrderExpress($orderSupplier) {
        $data = [
            'method' => 'orderExpress',// jingdong.ctp.order.getLogistics
            'data'   => [
                'customerId'    => $this->config['customerId'],//客户id，客户唯一身份标识
                'channelId'     => $this->config['channelId'],//渠道id，客户对应的细分渠道标识
                'appKey'        => $this->config['appKey'],//客户应用唯一标识
                'pin'           => $this->config['otherPin'],//订单对应的下单账号
                'orderId'       => $orderSupplier['thirdpart_order_sn'],//京东订单号
                'open_id_buyer' => $this->config['otherPin'],//订单对应的下单账号
            ],
        ];
        $res1 = $this->execute($data);
        if ($res1['code'] != Normal::SUC) {
            return $res1;
        }
        if (!isset($res1['data']['result']['data'])) {
            return Normal::returnCode(Normal::FAIL, "物流运单号查询失败1", $res1['data']);
        }
        $expressNoArr = reset($res1['data']['result']['data']);
        $expressNo    = $expressNoArr['waybillCode'] ?? '';
        if (empty($expressNo)) {
            return Normal::returnCode(Normal::FAIL, "物流运单号查询失败2", $res1['data']);
        }
        if(substr($expressNo, 0, 2) == "JD"){
            $expressName = '京东快递';
        }else{
            $expressName = '';
        }
        //查询配送方式
        // $res2 = $this->getOrderDetail($orderSupplier);
        // if ($res2['code'] != Normal::SUC) {
        //     return $res2;
        // }
        // if (!isset($res2['data']['result']['data']['shipment'])) {
        //     return Normal::returnCode(Normal::FAIL, "物流公司查询失败1", $res2['data']);
        // }
        // $expressNameArr = $res2['data']['result']['data']['shipment'] ?? [];
        // if (empty($expressNameArr)) {
        //     return Normal::returnCode(Normal::FAIL, "物流公司查询失败2", $res2['data']);
        // }
        // $expressName = $expressNameArr['shipmentType'] ?? '';
        // if (empty($expressName)) {
        //     return Normal::returnCode(Normal::FAIL, "物流公司查询失败3", $res2['data']);
        // }
        return Normal::returnCode(Normal::SUC, "物流查询成功", [
            'jdOrderSn'   => $orderSupplier['thirdpart_order_sn'],
            'expressNo'   => $expressNo,
            'expressName' => $expressName,
        ]);
    }

    /**
     * 查询订单详情
     * @param $orderSupplier
     * @return array
     */
    public function getOrderDetail($orderSupplier) {
        $data = [
            'method' => 'orderDetail',// jingdong.ctp.order.getOrderDetail
            'data'   => [
                'customerId' => $this->config['customerId'],//客户id，客户唯一身份标识
                'channelId'  => $this->config['channelId'],//渠道id，客户对应的细分渠道标识
                // 'clientIp'   => '81.68.188.148',//客户端请求ip
                'clientIp'   => $this->config['ycIp'],//客户端请求ip
                'appKey'     => $this->config['appKey'],//客户应用唯一标识
                'pin'        => $this->config['otherPin'],//订单对应的下单账号
                'orderId'    => $orderSupplier['thirdpart_order_sn'],//京东订单号
            ],
        ];
        return $this->execute($data);
    }

    //快递100查询物流公司名称
    public function queryExpressName($expressNo, $config){
        $key = $config['key'];
        $url = $config['autoNumberApi'].'?num='.$expressNo.'&key='.$key;
        $param = [
            'num' => $expressNo,
            'key' => $key,
        ];
        $parameter = [
            [
                'tag'    => self::SUPPLIER_CODE . '_queryExpressName',
                'uid'    => IdService::instance()->getOtherID(),
                'url'    => $url,
                'data'   => $param,
                'method' => 'get',
                'format' => 'form-data',
                'header' => [],
            ],
        ];
        $resTask   = TaskWorker::instance()->addTask($parameter, 'handleDiableTask');
        $resTask   = current($resTask);
        $result    = @json_decode($resTask['response']['result'], true);
        if(empty($result) || !is_array($result)){
            return Normal::returnCode(Normal::FAIL, "查询物流公司名称失败");
        }
        $expressNameArr = reset($result);
        $expressName = isset($expressNameArr['name']) && !empty($expressNameArr['name']) ? $expressNameArr['name'] : '';
        return Normal::returnCode(Normal::SUC, "物流公司查询成功", [
            'expressNo'   => $expressNo,
            'expressName' => $expressName,
        ]);
    }

    /**
     * CURL请求
     * @param $params
     * @return array
     */
    public function execute($params = []) {
        $method = $params['method'];
        if (!isset($this->config[$method])) {
            return Normal::returnCode(Normal::FAIL, "请求路由未设置");
        }
        $tokeRes = $this->getToken();
        if($tokeRes['code'] != Normal::SUC){
            return $tokeRes;
        }
        $sysParams["app_key"]           = $this->config['appKey'];
        $sysParams["v"]                 = '2.0';
        $sysParams["method"]            = $this->config[$method];
        $sysParams["timestamp"]         = date("Y-m-d H:i:s");
        $sysParams["access_token"]      = $tokeRes['data'];
        $sysParams["format"]            = 'json';
        $apiParams                      = $this->getApiParas($params['data']);
        $sysParams['360buy_param_json'] = $apiParams;
        $sysParams["sign"]              = $this->generateSign($sysParams);
        $requestUrl                     = $this->config['baseUrl'] . "?";
        $arr                            = [];
        foreach ($sysParams as $sysParamKey => $sysParamValue) {
            $arr[] = "$sysParamKey=" . urlencode($sysParamValue);
        }
        $requestUrl = $requestUrl . implode("&", $arr);
        $parameter  = [
            [
                'tag'    => self::SUPPLIER_CODE . '_' . $method,
                'uid'    => IdService::instance()->getOtherID(),
                'url'    => $requestUrl,
                'data'   => $params['data'],
                'method' => 'get',
                'format' => 'form-data',
                'header' => [],
            ],
        ];
        if (in_array($method, ['orderExpress', 'orderDetail'])) {
            $resTask = TaskWorker::instance()->addTask($parameter, 'handleDiableTask');
        } else {
            $resTask = TaskWorker::instance()->addTask($parameter);
        }
        $resTask = current($resTask);
        $result  = @json_decode($resTask['response']['result'], true);
        $sucStr  = str_replace('.', "_", $this->config[$method]) . '_response';
        if (isset($result[$sucStr])) {
            $r = $result[$sucStr];
            if ($r['result']['errCode'] != 200) {
                $msg = $r['result']['errMsg'] ?? '请求失败';
                return Normal::returnCode(Normal::FAIL, $msg, $r);
            }
            return Normal::returnCode(Normal::SUC, "请求成功", $r);
        }
        //这里处理京东的bug
        $sucStr = str_replace('.', "_", $this->config[$method]) . '_responce';
        if (isset($result[$sucStr])) {
            $r = $result[$sucStr];
            if ($r['result']['errCode'] != 200) {
                $msg = $r['result']['errMsg'] ?? '请求失败';
                return Normal::returnCode(Normal::FAIL, $msg, $r);
            }
            return Normal::returnCode(Normal::SUC, "请求成功", $r);
        }
        $msg = $result['errorMessage'] ?? '请求失败';
        return Normal::returnCode(Normal::FAIL, $msg, $result);
    }

    /**
     * 获取access_token
     * @author: hj
     */
    public function getToken() {
        if ($this->redis->exists(self::TOKEN_PREFIX)) {
            $token = $this->redis->get(self::TOKEN_PREFIX);
            return Normal::returnCode(Normal::SUC, "缓存获取access_token成功", $token);
        }
        $refresh_token = '';
        $configRfToken = $this->config['refreshToken'] ?? '';
        if ($this->redis->exists(self::REFRESH_TOKEN_PREFIX)) {
            $refresh_token = $this->redis->get(self::REFRESH_TOKEN_PREFIX);
            $refresh_token = $refresh_token ? $refresh_token : $configRfToken;
        } else {
            $refresh_token = $configRfToken;
        }
        //先查询是否有refresh_token 可以去刷新
        if ($refresh_token) {
            // https://open-oauth.jd.com/oauth2/refresh_token?app_key=XXXXX&app_secret=XXXXX&grant_type=refresh_token&refresh_token=XXXXX
            $url       = 'https://open-oauth.jd.com/oauth2/refresh_token';
            $param     = [
                'app_key'       => $this->config['appKey'],
                'app_secret'    => $this->config['appSecret'],
                'grant_type'    => 'refresh_token',
                'refresh_token' => $refresh_token,
            ];
            $reqUrl    = $url . '?' . http_build_query($param);
            $parameter = [
                [
                    'tag'    => self::SUPPLIER_CODE . '_refreshToken',
                    'uid'    => IdService::instance()->getOtherID(),
                    'url'    => $reqUrl,
                    'data'   => $param,
                    'method' => 'get',
                    'format' => 'form-data',
                    'header' => [],
                ],
            ];
            $resTask   = TaskWorker::instance()->addTask($parameter);
            $resTask   = current($resTask);
            $result    = @json_decode($resTask['response']['result'], true);
            if (!isset($result['access_token']) || !isset($result['expires_in']) || !isset($result['refresh_token'])) {
                $msg = $result['msg'] ?? 'refresh_token刷新access_token失败';
                return Normal::returnCode(Normal::FAIL, "refresh_token刷新access_token失败：access_token或expires_in或refresh_token不存在【{$msg}】", $result);
            }
            $token        = $result['access_token']; //access_token
            $tokenExp     = $result['expires_in'] - 3600; //access_token令牌有效时间, 单位秒
            $refreshToken = $result['refresh_token']; //access_token的刷新token
            $this->redis->set(self::TOKEN_PREFIX, $token, $tokenExp);
            $this->redis->set(self::REFRESH_TOKEN_PREFIX, $refreshToken);
            return Normal::returnCode(Normal::SUC, "refresh_token刷新access_token成功", $token);
        }
        //如果不能刷新 没有就先尝试去创建token
        $code = $this->config['code'];
        if ($code) {
            $tokenCreateRes = $this->createAccessToken();
            if ($tokenCreateRes['code'] != Normal::SUC) {
                return Normal::returnCode(Normal::FAIL, "code创建access_token失败【{$tokenCreateRes['msg']}】");
            }
            return Normal::returnCode(Normal::SUC, "缓存获取access_token成功", $tokenCreateRes['data']);
        }
        return Normal::returnCode(Normal::FAIL, "获取access_token失败,请重新操作授权!");
    }

    /**
     * 生成access_token
     * 文档：https://open.jd.com/home/home/#/doc/common?listId=1908
     * @return array
     * @author: hj
     */
    public function createAccessToken() {
        // https://open-oauth.jd.com/oauth2/access_token?app_key=XXXXX&app_secret=XXXXX&grant_type=authorization_code&code=XXXXX
        $url       = 'https://open-oauth.jd.com/oauth2/access_token';
        $param     = [
            'app_key'    => $this->config['appKey'],
            'app_secret' => $this->config['appSecret'],
            'grant_type' => 'authorization_code',
            'code'       => $this->config['code'],
        ];
        $reqUrl    = $url . '?' . http_build_query($param);
        $parameter = [
            [
                'tag'    => self::SUPPLIER_CODE . '_createAccessToken',
                'uid'    => IdService::instance()->getOtherID(),
                'url'    => $reqUrl,
                'data'   => $param,
                'method' => 'get',
                'format' => 'form-data',
                'header' => [],
            ],
        ];
        $resTask   = TaskWorker::instance()->addTask($parameter);
        $resTask   = current($resTask);
        $result    = @json_decode($resTask['response']['result'], true);
        if (!isset($result['access_token']) || !isset($result['expires_in']) || !isset($result['refresh_token'])) {
            $msg = $result['msg'] ?? '获取access_token失败';
            return Normal::returnCode(Normal::FAIL, "access_token或expires_in或refresh_token不存在【{$msg}】", $result);
        }
        $token        = $result['access_token']; //access_token
        $tokenExp     = $result['expires_in'] - 3600; //access_token令牌有效时间, 单位秒
        $refreshToken = $result['refresh_token']; //access_token的刷新token
        $this->redis->set(self::TOKEN_PREFIX, $token, $tokenExp);
        $this->redis->set(self::REFRESH_TOKEN_PREFIX, $refreshToken);
        return Normal::returnCode(Normal::SUC, "缓存获取access_token成功", $token);
    }

    /**
     * 签名计算
     * @author: hj
     */
    protected function generateSign($params) {
        ksort($params);
        $stringToBeSigned = $this->config['appSecret'];
        foreach ($params as $k => $v) {
            if ("@" != substr($v, 0, 1)) {
                $stringToBeSigned .= "$k$v";
            }
        }
        unset($k, $v);
        $stringToBeSigned .= $this->config['appSecret'];
        return strtoupper(md5($stringToBeSigned));
    }

    /**
     * 应用参数json化
     * @author: hj
     */
    protected function getApiParas($apiParas) {
        if (empty($apiParas)) {
            return "{}";
        }
        return json_encode($apiParas);
    }

}